const jwt = require("jsonwebtoken");
const { JWT_SECRET } = require("../config/config.default");

const { tokenExpiredError, invalidToken, hasNotAdminPermission } = require("../constant/error.type");

/**
 * 身份认证中间件（判断用户是否已经登录）
 * @param {*} ctx 请求上下文
 * @param {*} next 放行函数
 */
const auth = async (ctx, next) => {
  try {
    // 给authorization设置默认值为空字符串（当解构失败时authorization为""），从请求头中获取authorization
    const { authorization = "" } = ctx.request.header;
    // console.log("authorization", authorization);
    // Bearer是送信人的意思，Bearer是固定的，后面跟着空格，空格后面才是token
    const token = authorization.replace("Bearer ", "");
    // console.log("token", token);
    // 使用私钥验证token，返回的结果user中包含了payload的信息（id, user_name, is_admin）
    const user = jwt.verify(token, JWT_SECRET);
    // 把返回结果user挂到ctx.state.user上，后续就可以通过ctx.state.user拿到用户信息
    ctx.state.user = user;
  } catch (error) {
    // 里面的error.name那些错误是jwt.verify抛出的错误
    switch (error.name) {
      // 如果是token过期错误
      case "TokenExpiredError":
        console.error("token已过期", error);
        ctx.app.emit("error", tokenExpiredError, ctx);
        return;
      // 如果是token无效错误
      case "JsonWebTokenError":
        console.error("无效的token", error);
        ctx.app.emit("error", invalidToken, ctx);
        return;

      default:
        console.error("授权失败", error);
        ctx.app.emit("error", invalidToken, ctx);
        return;
    }
  }
  // 交由下一个中间件处理
  await next();
};

/**
 * 授权中间件（判断用户是否有管理员的权限）
 * @param {*} ctx 请求上下文
 * @param {*} next 放行函数
 */
const hadAdminPermission = async (ctx, next) => {
  const { is_admin } = ctx.state.user;
  if (!is_admin) {
    console.error("该用户没有管理员的权限", ctx.state.user);
    return ctx.app.emit("error", hasNotAdminPermission, ctx);
  }
  // 交由下一个中间件处理
  await next();
};

module.exports = {
  auth,
  hadAdminPermission,
};
